package kpi.javatraining6.gnatiuk.tests;

import kpi.javatraining6.gnatiuk.src.tester.Authorizer;
import kpi.javatraining6.gnatiuk.src.tester.Logger;
import kpi.javatraining6.gnatiuk.src.tester.inout.FileSaver;
import kpi.javatraining6.gnatiuk.src.tester.question.Question;
import kpi.javatraining6.gnatiuk.src.tester.question.SingleAnswerQuestion;
import kpi.javatraining6.gnatiuk.src.tester.readers.UserDOMSaver;
import kpi.javatraining6.gnatiuk.src.tester.user.User;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.util.ArrayList;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;


public class UserDOMSaverTest {
    private Document doc;
    private XPath xpath;
    private Authorizer authorizer;
    @Before
    public void setUp() {
        XPathFactory factory = XPathFactory.newInstance();
        xpath = factory.newXPath();
        authorizer = new Authorizer();
        rebuild();
    }

    @Test
    public void testGetInstance() throws Exception {
         assertEquals(UserDOMSaver.class, UserDOMSaver.getInstance().getClass());
    }

    @Test
    public void testNewUser() {
        String userName = RandomStringUtils.randomAlphabetic(20);
        User newUser = new User(userName, "1");
        authorizer.authenticateUser(newUser);
        assertTrue(newUser.getStartedTopics().isEmpty());
        deleteUser(userName);
    }

    @Test
    public void testSaveNewUserProgress() throws Exception {
        String userName = RandomStringUtils.randomAlphabetic(20);
        User newUser = new User(userName, "1");
        authorizer.authenticateUser(newUser);
        Question question = new SingleAnswerQuestion("EASY", "", new ArrayList<String>(), new ArrayList<String>());
        newUser.getCurrentProgress("OOP").addToAnswered(question, new ArrayList<String>());
        UserDOMSaver.getInstance().saveUserProgress(newUser);
        rebuild();
        XPathExpression expr = xpath.compile("//user[last()]/userProgressMap/progressItem");
        NodeList progressList = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);
        assertTrue(progressList.getLength() > 0);
        deleteUser(userName);
    }

    public void deleteUser(String userName) {
        String xPathExpression = String.format("//user[last()]", userName);
        rebuild();
        try {
            XPathExpression expr = xpath.compile(xPathExpression);
            Node someUser = (Node)expr.evaluate(doc, XPathConstants.NODE);
                someUser.getParentNode().removeChild(someUser);
                FileSaver.saveFile(doc, "users.xml");
        } catch (XPathExpressionException e) {
            Logger.getInstance().recordExceptionalEvent(e);
            System.exit(1);
        }

    }

    private void rebuild() {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            doc = builder.parse("users.xml");
        } catch (ParserConfigurationException | IOException | SAXException e) {
            Logger.getInstance().recordExceptionalEvent(e);
        }
    }

}
